<!--
  字典下拉选择组件 - 基于字典数据的下拉选择框
  
  使用示例：
  1. 基础单选下拉：
  <FormDictSelectItem 
    v-model="form.status" 
    prop="status" 
    label="状态" 
    dict-type-code="user_status" 
  />
  
  2. 多选下拉：
  <FormDictSelectItem 
    v-model="form.tags" 
    prop="tags" 
    label="标签" 
    dict-type-code="user_tags"
    :multiple="true"
  />
  
  3. 自定义选项过滤：
  <FormDictSelectItem 
    v-model="form.status" 
    prop="status" 
    label="状态" 
    dict-type-code="user_status"
    :option-filter="(item) => item.dictCode !== '0'"
  />
-->
<template>
  <el-form-item
    v-bind="$attrs"
    :prop="prop"
    :label="label"
    :rules="rules"
    :required="required"
    :label-width="labelWidth"
    :error="error"
    :show-message="showMessage"
    :inline-message="inlineMessage"
    :size="size"
  >
    <!-- 下拉选择框 -->
    <el-select
      :value="modelValue"
      @update:modelValue="handleChange"
      :placeholder="placeholder"
      :disabled="disabled"
      :clearable="clearable"
      :multiple="multiple"
      :filterable="filterable"
      :allow-create="allowCreate"
      :reserve-keyword="reserveKeyword"
      :collapse-tags="collapseTags"
      :collapse-tags-tooltip="collapseTagsTooltip"
      :max-collapse-tags="maxCollapseTags"
      :teleported="teleported"
      :persistent="persistent"
      :automatic-dropdown="automaticDropdown"
      :fit-input-width="fitInputWidth"
      :suffix-icon="suffixIcon"
      :prefix-icon="prefixIcon"
      :clear-icon="clearIcon"
      :loading="loading"
      :loading-text="loadingText"
      :no-match-text="noMatchText"
      :no-data-text="noDataText"
      :popper-class="popperClass"
      :popper-style="popperStyle"
      :popper-options="popperOptions"
      :teleport-to="teleportTo"
      :tag-type="tagType"
      :validate-event="validateEvent"
      :size="size"
      :effect="effect"
      @change="handleChange"
      @visible-change="handleVisibleChange"
      @remove-tag="handleRemoveTag"
      @clear="handleClear"
      @blur="handleBlur"
      @focus="handleFocus"
    >
      <el-option
        v-for="option in filteredOptions"
        :key="option.dictCode"
        :label="option.dictName"
        :value="option.dictCode"
      />
    </el-select>

    <!-- 加载状态 -->
    <div v-if="loading" class="dict-loading">
      <el-icon class="is-loading"><Icon icon="mdi:loading" /></el-icon>
      <span>{{ loadingText }}</span>
    </div>

    <!-- 错误状态 -->
    <div v-else-if="errorMessage" class="dict-error">
      <el-icon><Icon icon="mdi:alert-circle" /></el-icon>
      <span>{{ errorMessage }}</span>
    </div>
  </el-form-item>
</template>

<script setup lang="ts">
import { ref, computed, watch, onMounted } from 'vue'
import { ElFormItem, ElSelect, ElOption, ElIcon } from 'element-plus'
import { Icon } from '@iconify/vue'
import { useDictStore } from '@/store/modules/dict'
import type { DictDTO } from '@/api/system/dict'

interface Props {
  // 表单相关属性
  modelValue?: string | number | string[] | number[]
  prop?: string
  label?: string
  rules?: any
  required?: boolean
  labelWidth?: string
  error?: string
  showMessage?: boolean
  inlineMessage?: boolean
  size?: 'large' | 'default' | 'small'

  // 字典相关属性
  dictTypeCode: string
  // 选项过滤函数
  optionFilter?: (item: DictDTO) => boolean
  // 选项格式化函数
  optionFormatter?: (item: DictDTO) => DictDTO
  // 是否自动加载字典数据
  autoLoad?: boolean

  // 下拉选择框属性
  placeholder?: string
  disabled?: boolean
  clearable?: boolean
  multiple?: boolean
  filterable?: boolean
  allowCreate?: boolean
  reserveKeyword?: boolean
  collapseTags?: boolean
  collapseTagsTooltip?: boolean
  maxCollapseTags?: number
  teleported?: boolean
  persistent?: boolean
  automaticDropdown?: boolean
  fitInputWidth?: boolean
  suffixIcon?: string
  prefixIcon?: string
  clearIcon?: string
  loadingText?: string
  noMatchText?: string
  noDataText?: string
  popperClass?: string
  popperStyle?: any
  popperOptions?: any
  teleportTo?: string | HTMLElement
  tagType?: 'success' | 'info' | 'warning' | 'danger'
  validateEvent?: boolean
  effect?: 'dark' | 'light' | 'plain'
}

const props = withDefaults(defineProps<Props>(), {
  autoLoad: true,
  placeholder: '请选择',
  clearable: true,
  multiple: false,
  filterable: false,
  allowCreate: false,
  reserveKeyword: false,
  collapseTags: false,
  collapseTagsTooltip: false,
  maxCollapseTags: 3,
  teleported: true,
  persistent: false,
  automaticDropdown: false,
  fitInputWidth: false,
  loadingText: '加载中...',
  noMatchText: '无匹配数据',
  noDataText: '无数据',
  validateEvent: true,
  effect: 'light',
  optionFilter: () => true,
  optionFormatter: (item: DictDTO) => item
})

interface Emits {
  (e: 'update:modelValue', value: string | number | string[] | number[]): void
  (e: 'change', value: string | number | string[] | number[]): void
  (e: 'visible-change', visible: boolean): void
  (e: 'remove-tag', value: string | number): void
  (e: 'clear'): void
  (e: 'blur', event: FocusEvent): void
  (e: 'focus', event: FocusEvent): void
}

const emit = defineEmits<Emits>()

const dictStore = useDictStore()
const loading = ref(false)
const errorMessage = ref('')
const dictOptions = ref<DictDTO[]>([])

// 过滤后的选项
const filteredOptions = computed(() => {
  return dictOptions.value.filter(props.optionFilter).map(props.optionFormatter)
})

// 加载字典数据
const loadDictData = async () => {
  if (!props.autoLoad || !props.dictTypeCode) return

  loading.value = true
  errorMessage.value = ''

  try {
    const dictList = await dictStore.getDictList(props.dictTypeCode)
    dictOptions.value = dictList
  } catch (err) {
    errorMessage.value = '加载字典数据失败'
    console.error('加载字典数据失败:', err)
  } finally {
    loading.value = false
  }
}

// 处理值变化
const handleChange = (value: string | number | string[] | number[]) => {
  emit('update:modelValue', value)
  emit('change', value)
}

// 处理可见性变化
const handleVisibleChange = (visible: boolean) => {
  emit('visible-change', visible)
}

// 处理移除标签
const handleRemoveTag = (value: string | number) => {
  emit('remove-tag', value)
}

// 处理清空
const handleClear = () => {
  emit('clear')
}

// 处理失焦
const handleBlur = (event: FocusEvent) => {
  emit('blur', event)
}

// 处理聚焦
const handleFocus = (event: FocusEvent) => {
  emit('focus', event)
}

// 监听字典类型编码变化，重新加载数据
watch(
  () => props.dictTypeCode,
  (newTypeCode) => {
    if (newTypeCode && props.autoLoad) {
      loadDictData()
    }
  },
  { immediate: true }
)

onMounted(() => {
  if (props.autoLoad && props.dictTypeCode) {
    loadDictData()
  }
})
</script>

<style lang="less" scoped>
.dict-loading,
.dict-error {
  display: flex;
  align-items: center;
  gap: 4px;
  color: #909399;
  font-size: 12px;
}

.dict-error {
  color: #f56c6c;
}
</style>
